#ifndef BMD_STAGE_H
#define BMD_STAGE_H

#include <iostream>
#include <vector>
#include "gameobjs.h"

using namespace std;


/*
	An attempt at movement can have different possible results.
	This would especially be used for sound effects with collision 
	with various walls.
	At the moment all it is used for is:
	
	result_type =
					1     <--- powerup collected
					0     <--- simple allowed move
					-1    <--- collision with bomb
					-2    <--- collision with a bomber
					-3    <--- collision with unpathable wall

	example future applications:
	                -4    <--- collision with bricks
					-5    <--- collision with player
*/

static const int mrtWALL = -3;
static const int mrtBOMBER = -2;
static const int mrtBOMB = -1;
static const int mrtFREE = 0;
static const int mrtPUP = 1;

/*
Structure containing the result of a move attempt 
by a bomb or a bomber. Generally more specific than 
needed - however it is used to infer when bomb kicking occurs 
as opposed to a simple collision.
In a more elaborate game one could, for example, play a different 
sound effect depending on what type of collision occured.
*/
struct MoveResult
{
private:
	int result_type;
	int collidee_id;

public:

	MoveResult(const int in_result_type){result_type = in_result_type; collidee_id = -1;}
	MoveResult(){result_type = -1; collidee_id = -1;}
	bool success()
	{ return result_type >= 0; } //a positive result means success

	int get_type()
	{ return result_type; }

	void set_collidee_id(int in_id) {collidee_id = in_id;}
	int get_collidee_id() {return collidee_id;}
};


/*
Stores data about which game objects were 
effected/created by an explosion.
*/
struct ExplosionResult
{
	vector<int> ef_bombers;
	vector<int> ef_bombs;
	vector<int> ef_powerups;
	vector<PowerUp> created_powerups;
	ExplosionDat explosion_data;

	ExplosionResult()
	{
	}
};

//simple class reprenting a stage tile's type and pathability.
class TileType
{
public:
	int type_index;

	bool pathable()
	{
		if(type_index != tBRICK && type_index != tBLOCK)
			return true;
		return false;
	}
};


/*
Class that represents a single tile on the 
stage. A stage is an 2D-array of tiles.

A tile contains IDs that correspond to specific 
bombers or bombs in the Engine class.

A tile may only contain a single bomb xor a single bomber.

A tile can be reserved for movement by a bomber about to move to 
it. In this case other objects cannot attempt to move to the tile.
*/
class Tile
{
public:
	TileType type;
	//bool has_bomb;
	//bool has_bomber;
    int bomb_id;    //bomb_id = -1 <=> no bomb
	int bomber_id;  //bomber_id = -1 <=> no bomber
	int powerup_id; //...
	bool bomber_reserved;//if a bomber is approved to move to a tile, it becomes reserved
	bool bomb_reserved; //similar to bomber_reserved

	/* NOTE: the reason there are two types of reserved is in case
		there is ever a different result depending on who one colides with.
		A bomb detonation? Or just a different sound effect.*/

	//can an explosion pass theough this tile?
	//disregards "reserved" fields
	bool explosion_pathable()
	{
		return type.pathable()
			&& bomb_id == -1;
	}

	//can this tile be moved to?
	bool clear_to_move()
	{
		return type.pathable() 
			&& bomb_id == -1
			&& bomber_id == -1
			&& !bomber_reserved
			&& !bomb_reserved;
	}

	//can a bomb be placed on this tile?
	bool clear_to_bomb(const int owner_id)
	{
		return  type.pathable()
			&& bomb_id == -1
			&& bomber_id == owner_id
			&& !bomber_reserved
			&& !bomb_reserved;
			
	}

	inline bool has_bomber() { return (bomber_id >= 0);}
	inline bool has_powerup() { return (powerup_id >= 0);}
	inline bool has_bomb() { return (bomb_id >= 0);}


	//removes the remaining data left by exploding bombs.
	//called in the main engine loop.
	void clear_bomb_residue()
	{
		bomb_id = -1;
	}

	//clears a tile
	void set_empty()
	{
		type.type_index = tEMPTY;
		bomb_id = bomber_id = powerup_id = -1;
		bomber_reserved = bomb_reserved = false;
	}

	//informs a tile an explosion has passed theough it.
	//potentially creates powerups
	PowerUp explode(const Coordinates & tile_coords)
	{
		PowerUp temppowerup;
		temppowerup.id = -1;
		//add destruction of bricks -> dropping of powerups, change in type essentially
		if(type.type_index == tBRICK)
		{
			type.type_index = tEXPLOSION_BRICK;//tBRICK_EXPLOSION;

			if(prob(POWERUP_ODDS))//if a power up is to be created
			{
				temppowerup.coords = tile_coords;
				temppowerup.power_type_index = rint(pOVER_MAX_INDEX); //first valid powerup index is 0
				temppowerup.id = 0; //temporary ID indicating powerup creation
			}
		}
		else if(type.type_index == tEMPTY)
			type.type_index = tEXPLOSION;

		bomber_id = -1;

		return temppowerup;
	}

	// returns the ascii representation of a tile's contents
	char ascii_sym()
	{
		if(bomb_id >= 0)
		{
			if(bomber_id >= 0)
				return '%';
			else
				return '+';
		}
		else if(bomber_id >= 0)
			return 'B';

		if(type.type_index == 0)
			return '.';
		if(type.type_index == 1)
			return 'O';
		if(type.type_index == 2)
			return '0';

		return '?';
	}
};



/*
The class that anchors the various game objects, giving 
their relative positions actual meaning.

A stage is composed of tiles.
Stage operations modify these tiles or infer events (such as collision)
by comparing various fields within the tiles.

****For anyone attempting to modify this code****
The most likely causes of error when using Stage are:
- passing illogical IDs. This will cause missdetections.
- forgetting to clear IDs/reservations once objects are destroyed.
Special care should be taken to maintain these with appropriate function calls.
*/
class Stage
{
private:
	unsigned int H,W;
	Tile * tiles;
	bool tiles_declared;

public:

	//vector of starting locations of the bombers
	vector<Coordinates> starting_loc;

	//to be used once coordinates are checked
	inline unsigned int unsafe_tile_index(const Coordinates & coords) { return coords.x*H + coords.y; }
	inline unsigned int unsafe_tile_index(const unsigned int i, const unsigned int j) { return i*H + j;}

	inline bool coord_valid(const Coordinates & coords) { return (coords.x < W && coords.y < H); }
	inline bool coord_valid(const unsigned int i, const unsigned int j) { return (i < W && j < H);}

	//converts coordinates to a tile index
	unsigned int tile_index(const Coordinates & coords)
	{
		if(coord_valid(coords))
			return unsafe_tile_index(coords);

		return 0;
	}

	//used only for testing at the moment
	unsigned int tile_index(unsigned int i, unsigned int j)
	{
		Coordinates temp_coords(i,j);
		return tile_index(temp_coords);
	}

public:


	/*
		the engine requests a bomber movement to: dest_coords

		the result of this movement is returned as a MoveResult(see).
		  the possible outcomes are a collision, or if not, the bomber
		begins to move towards the destination tile, reserving it (making 
		it unpathable) and limiting its movement options (during the transition 
		the bomber can only move back towards its starting cell or keep proceeding).
		****The bomber can still place bombs****
	*/

	MoveResult bomber_CheckMove(const Coordinates & dest_coords)
	{
		unsigned int temp_index = tile_index(dest_coords);
		if(tiles[temp_index].clear_to_move())
		{
			MoveResult move_result(mrtFREE);
			return move_result;
		}
		if(tiles[temp_index].bomb_id >= 0)
		{
			MoveResult move_result(mrtBOMB);
			move_result.set_collidee_id(tiles[temp_index].bomb_id);
			return move_result;
		}
		

		MoveResult move_result(mrtWALL);
		return move_result;
	}

	//must perform check_move_bomber before this to avoid errors
	//reserves a bomber's destination tile
	void bomber_UnsafeCommenceMove(//const unsigned int bomber_id,
		        const Coordinates & dest_coords)
	{tiles[unsafe_tile_index(dest_coords)].bomber_reserved = true;}

	/*
		Once a bomber has proceeded to an adjacent tile, the stage is signaled.
		Tile states are changed.
	*/
	void bomber_InformTileChange(const unsigned int in_bomber_id,
		const Coordinates & from_bomber_coords,
		const Coordinates & to_bomber_coords)
	{
		unsigned int temp_index = tile_index(from_bomber_coords);
		tiles[temp_index].bomber_id = -1;
		tiles[temp_index].bomber_reserved = true;

		temp_index = tile_index(to_bomber_coords);
		tiles[temp_index].bomber_id = in_bomber_id;
		tiles[temp_index].bomber_reserved = false;
		//the bomber is now in this tile, it is no longer just 'move_reserved'
		//a nice way to keep move_reserved up to date
	}

	//the following must be called to inform a bomber entirely leaving a tile -
	//it is then no longer considered reserved.
	void bomber_InformTileClear(const Coordinates & vacant_bomber_coords)
	{
		tiles[tile_index(vacant_bomber_coords)].bomber_reserved = false;
	}





	/*
	The following functions perform exactly the same movement 
	features as above, but they apply to bombs.
	*/
	MoveResult bomb_CheckMove(const Coordinates & dest_coords)
	{
		unsigned int temp_index = tile_index(dest_coords);
		if(tiles[temp_index].clear_to_move())
		{
			MoveResult move_result1(mrtFREE);
			return move_result1;
		}

		MoveResult move_result2(mrtWALL);
		return move_result2;
	}

	//must perform check_move_bomb before this to avoid errors
	void bomb_UnsafeCommenceMove(//const unsigned int bomb_id,
		        const Coordinates & dest_coords)
	{tiles[unsafe_tile_index(dest_coords)].bomb_reserved = true;}

	/*
		Once a bomb has proceeded to an adjacent tile, the stage is signaled.
		Tile states are changed.
	*/
	void bomb_InformTileChange(const unsigned int in_bomb_id,
		const Coordinates & from_bomb_coords,
		const Coordinates & to_bomb_coords)
	{
		unsigned int temp_index = tile_index(from_bomb_coords);
		tiles[temp_index].bomb_id = -1;
		tiles[temp_index].bomb_reserved = true;

		temp_index = tile_index(to_bomb_coords);
		tiles[temp_index].bomb_id = in_bomb_id;
		tiles[temp_index].bomb_reserved = false;
		//the bomb is now in this tile, it is no longer just 'move_reserved'
		//a nice way to keep move_reserved up to date
	}

	//the following must be called to inform a bomb entirely leaving a tile -
	//it is then no longer considered reserved.
	void bomb_InformTileClear(const Coordinates & vacant_bomb_coords)
	{
		tiles[tile_index(vacant_bomb_coords)].bomb_reserved = false;
	}
















	/*
		Detonates a single bomb, returning a list of bombs, bombers and
		powerups effected.
		
		A tile on which a bomb detonates receives a special index of -2
		which is cleared soon after by the Engine. This is used to effectively
		cause bomb's explosions to be unable to penetrate bombs that have 
		exploded in the same chain reaction.

		Bombs explode in a 'cross' shape, expanding vertically and horizontally 
		by the number of tiles based on 'power'. As a result the implementation 
		is very straightforward.
		Explosions in a direction are stopped once they encounter other bombs, 
		bricks or blocks.
	*/
	ExplosionResult detonate_bomb(const Coordinates & coords, const unsigned int power)
	{
		ExplosionResult result;

		PowerUp temppowerup;
		Coordinates temp_coords_n;
		Coordinates temp_coords_p;
		unsigned int temp_index;
		bool n_pers, p_pers; //is the explosion persisting, or was it blocked?
		//n = negative
		//p = positive

		if(tiles[tile_index(coords)].has_bomber())
			result.ef_bombers.push_back(tiles[tile_index(coords)].bomber_id); //techically i guess you know its the bomb's owner's id
		tiles[tile_index(coords)].bomb_id = -2; //DO NOT 'remove' the bomb from the tile system until later

		result.explosion_data.center = coords;

		n_pers = p_pers = true;
		temp_coords_n = coords;
		temp_coords_p = coords;
		for(unsigned int i = 0; i < power; i++)
		{
			if(n_pers)
			{	temp_coords_n.x--;
				if(temp_coords_n.x >= 0)
				{
					temp_index = tile_index(temp_coords_n);
					
					if(tiles[temp_index].has_bomber())
						result.ef_bombers.push_back(tiles[temp_index].bomber_id);
					if(tiles[temp_index].has_powerup())
						result.ef_powerups.push_back(tiles[temp_index].powerup_id);
					
					if(tiles[temp_index].has_bomb())
					{	result.ef_bombs.push_back(tiles[temp_index].bomb_id);
						n_pers = false; 
						result.explosion_data.dW = i;}
					else if(! tiles[temp_index].explosion_pathable()) //if its pathable, explosion persists - else is valid
					{
						n_pers = false;
						result.explosion_data.dW = i;}

					temppowerup = tiles[temp_index].explode(temp_coords_n);
					if(temppowerup.id >= 0) //ID used as sentinel for powerup creation
					{
						result.created_powerups.push_back(temppowerup);
					}
			}	}
			

			if(p_pers)
			{	temp_coords_p.x++;
				if(temp_coords_p.x < W)
				{
					temp_index = tile_index(temp_coords_p);
					
					if(tiles[temp_index].has_bomber())
						result.ef_bombers.push_back(tiles[temp_index].bomber_id);
					if(tiles[temp_index].has_powerup())
						result.ef_powerups.push_back(tiles[temp_index].bomber_id);

					if(tiles[temp_index].has_bomb())
					{	result.ef_bombs.push_back(tiles[temp_index].bomb_id);
						p_pers = false;
						result.explosion_data.dE = i;}
					else if(! tiles[temp_index].explosion_pathable()) //if its pathable, explosion persists - else is valid
					{	p_pers = false;
						result.explosion_data.dE = i;}

					temppowerup = tiles[temp_index].explode(temp_coords_p);
					if(temppowerup.id >= 0) //ID used as sentinel for powerup creation
					{
						result.created_powerups.push_back(temppowerup);
					}
			}	}
		}
		if(n_pers) result.explosion_data.dW = power;
		if(p_pers) result.explosion_data.dE = power;


		//the following code should be identical but use .y over .x, H over W, and dS over dW/dN over dE
		n_pers = p_pers = true;
		temp_coords_n = coords;
		temp_coords_p = coords;
		for(unsigned int i = 0; i < power; i++)
		{
			if(n_pers)
			{	temp_coords_n.y--;
				if(temp_coords_n.y >= 0)
				{
					temp_index = tile_index(temp_coords_n);
					
					if(tiles[temp_index].has_bomber())
						result.ef_bombers.push_back(tiles[temp_index].bomber_id);
					if(tiles[temp_index].has_powerup())
						result.ef_powerups.push_back(tiles[temp_index].powerup_id);
					
					if(tiles[temp_index].has_bomb())
					{	result.ef_bombs.push_back(tiles[temp_index].bomb_id);
						n_pers = false;
						result.explosion_data.dN = i;}
					else if(! tiles[temp_index].explosion_pathable()) //if its pathable, explosion persists - else is valid
					{
						n_pers = false;
						result.explosion_data.dN = i;}

					temppowerup = tiles[temp_index].explode(temp_coords_n);
					if(temppowerup.id >= 0) //ID used as sentinel for powerup creation
					{
						result.created_powerups.push_back(temppowerup);
					}
			}	}
			

			if(p_pers)
			{	temp_coords_p.y++;
				if(temp_coords_p.y < H)
				{
					temp_index = tile_index(temp_coords_p);
					
					if(tiles[temp_index].has_bomber())
						result.ef_bombers.push_back(tiles[temp_index].bomber_id);
					if(tiles[temp_index].has_powerup())
						result.ef_powerups.push_back(tiles[temp_index].bomber_id);

					if(tiles[temp_index].has_bomb())
					{	result.ef_bombs.push_back(tiles[temp_index].bomb_id);
						p_pers = false;
						result.explosion_data.dS = i;}
					else if(! tiles[temp_index].explosion_pathable()) //if its pathable, explosion persists - else is valid
					{	p_pers = false;
						result.explosion_data.dS = i;}

					temppowerup = tiles[temp_index].explode(temp_coords_p);
					if(temppowerup.id >= 0) //ID used as sentinel for powerup creation
					{
						result.created_powerups.push_back(temppowerup);
					}
			}	}
		}
		if(n_pers) result.explosion_data.dN = power;
		if(p_pers) result.explosion_data.dS = power;
		return result;
	}// end detonate_bomb


	/*
		tells the stage to place the passed bomber based on bomber.coords.
		returns true if the placement is allowed. otherwise returns false.
	*/
	bool place_bomber(Bomber & bomber)
	{
		unsigned int temp_tile_index = unsafe_tile_index(bomber.coords);
		if(tiles[temp_tile_index].clear_to_move())
		{
			tiles[temp_tile_index].bomber_id = bomber.get_id();
			return true;
		}
		return false;
	}

	//the input is presumed to be safe - only called where powerups can be formed
	void place_powerup(PowerUp & powerup)
	{
		unsigned int temp_tile_index = unsafe_tile_index(powerup.coords);
		tiles[temp_tile_index].powerup_id = powerup.id;
	}

	//attempts to place a bomb at some location with the given id.
	//location based on bomber.coords.
	bool place_bomb(Bomber & bomber, const unsigned int & in_bomb_id)
	{
		unsigned int temp_tile_index = unsafe_tile_index(bomber.coords);
		if(tiles[temp_tile_index].clear_to_bomb(bomber.get_id()))
		{
			tiles[temp_tile_index].bomb_id = in_bomb_id;
			return true;
		}
		return false;
	}

	/*
	These clear the explosion "graphic" residue from a tile 
	(see Explosion class).
	Mostly cosmetic and informative for AI.
	*/
	void clear_explosion(const Coordinates & coords)
	{
		if(coord_valid(coords))
		{tiles[unsafe_tile_index(coords)].type.type_index = (unsigned int)tEMPTY;}
	}
	void clear_explosion_brick(const Coordinates & coords)
	{
		if(coord_valid(coords))
		{
			unsigned int temp_index = unsafe_tile_index(coords);
			if(tiles[temp_index].type.type_index == tEXPLOSION_BRICK)
				tiles[temp_index].type.type_index = tEMPTY;
		}
	}

	/*
	Used mainly to clear the -2 flag used during the detonate_bomb()
	function call. Called in the engine.
	*/
	void remove_bomb_residue(const Coordinates & coords)
	{
		if(coord_valid(coords))
		{tiles[unsafe_tile_index(coords)].clear_bomb_residue();}
	}


	//simple destructor. clears the tile system.
	~Stage()
	{
		if(tiles_declared)
			delete [] tiles;
	}

	//returns the type of the tile at coords
	int tile_tinfo(const Coordinates & coords)
	{
		if(coord_valid(coords))
		{
			return tiles[unsafe_tile_index(coords)].type.type_index;
		}
		return -1;
	}

	//checks if the type of the tile is "tindex" at coords
	bool check_tinfo(const Coordinates & coords, int tindex)
	{
		if(coord_valid(coords))
		{
			return tiles[unsafe_tile_index(coords)].type.type_index == tindex;
		}
		return false;
	}

	//removes a powerup from the stage,
	//returns its type, to be used to 'give' the powerup to 
	//whoever picked it up.
	int acquire_powerup(const Coordinates & coords)
	{
		if(coord_valid(coords))
		{
			unsigned int temp_index = unsafe_tile_index(coords);
			int ret_id = tiles[temp_index].powerup_id;
			tiles[temp_index].powerup_id = -1; //remove power up id, effectivelly "picking it up"

			return ret_id;
		}
		return -1;
	}

	unsigned int getH(){return H;}
	unsigned int getW(){return W;}
	


	
	/*
	TESTING CODE:
	- The following is an ascii dump.
	- In order to use it, uncomment this functions call 
	in the engine.
	- I can't guarantee a console will show with wxWidgets being 
	used. If the reader really wants an ascii dump, write a simpler 
	set of calls from main that do not use wxWidgets.
	*/
	void ascii_dump()
	{
		for(unsigned int j = 0; j < H; j++)
		{
			cout << endl;
			for(unsigned int i = 0; i < W; i++)
				cout << tiles[unsafe_tile_index(i,j)].ascii_sym();
		}
		cout << endl;
		cout << "-----------------------------";
	}





	/*
	Generates a random map with the appropriate dimensions, 
	brinck density, and a up to four bombers.

	Returns the bomber's starting coordinates in a vector.
	*/
	vector<Coordinates> gen_random_map(unsigned int in_H, 
						unsigned int in_W, 
						unsigned int nP, //nP - number of players
						float brick_density)
	{
		H = in_H;
		W = in_W;

		if(H % 2 == 0) //if H is not even, map will be lopsided
			H--;
		if(W % 2 == 0) //similarly
			W--;

		tiles = new Tile[H*W];
		tiles_declared = true;

		int sH, sW; //starting pointed related, modified H,W
		int rnd;

		vector<Coordinates>::iterator start_pos;

		for(unsigned int i = 0; i < W; i++)
			for(unsigned int j = 0; j < H; j++)
				tiles[tile_index(i,j)].set_empty();

		//place 'field' blocks
		for(unsigned int i = 0; i < W; i+=2)
			for(unsigned int j = 0; j < H; j+=2)
				tiles[tile_index(i,j)].type.type_index = tBLOCK;

		//place bricks with ~density
		for(unsigned int i = 1; i < W - 1; i++)
		{
			if(i % 2 == 1) //free row
			{
				for(unsigned int j = 1; j < H - 1; j++)
				{
					if(prob(brick_density))
						tiles[tile_index(i,j)].type.type_index = tBRICK;
				}
			}
			else //block row
			{
				for(unsigned int j = 1; j < H - 1; j+=2)
				{
					if(prob(brick_density))
						tiles[tile_index(i,j)].type.type_index = tBRICK;
				}
			}
		}

		//place 'border' blocks
		for(unsigned int i = 0; i < W; i++)
		{
			tiles[tile_index(i,0)].type.type_index = 2;
			tiles[tile_index(i,H-1)].type.type_index = 2;
		}

		for(unsigned int j = 1; j < H -1; j++)
		{
			tiles[tile_index(0,j)].type.type_index = 2;
			tiles[tile_index(W-1,j)].type.type_index = 2;
		}

		//place player starting locations


		sH = H - 2;
		sW = W - 2;
		Coordinates locNW(1,1), locNE(sW,1), locSW(1,sH), locSE(sW,sH);
		rnd = rint(4);
		if(nP >= 4)
		{
			starting_loc.push_back(locNW);
			starting_loc.push_back(locNE);
			starting_loc.push_back(locSW);
			starting_loc.push_back(locSE);
		}
		else if(nP == 3)
		{
			if(rnd == 0)
			{	starting_loc.push_back(locNE);
				starting_loc.push_back(locSW);
				starting_loc.push_back(locSE);}
			else if(rnd == 1)
			{	starting_loc.push_back(locNW);
				starting_loc.push_back(locSW);
				starting_loc.push_back(locSE);}
			else if(rnd == 2)
			{	starting_loc.push_back(locNW);
				starting_loc.push_back(locNE);
				starting_loc.push_back(locSE);}
			else
			{	starting_loc.push_back(locNW);
				starting_loc.push_back(locNE);
				starting_loc.push_back(locSW);}
		}
		else if(nP == 2)
		{
			if(rnd == 0)
			{	starting_loc.push_back(locNE);
				starting_loc.push_back(locNW);}
			else if(rnd == 1)
			{	starting_loc.push_back(locNE);
				starting_loc.push_back(locSW);}
			else if(rnd == 2)
			{	starting_loc.push_back(locNW);
				starting_loc.push_back(locSE);}
			else
			{	starting_loc.push_back(locSE);
				starting_loc.push_back(locSW);}
		}
		else
		{
			if(rnd == 0)		starting_loc.push_back(locNE);
			else if(rnd == 1)	starting_loc.push_back(locNW);
			else if(rnd == 2)	starting_loc.push_back(locSW);
			else				starting_loc.push_back(locSE);
		}




		/*
		The following part of the map generator creates 
		the starting locations, clearing three blocks in an L 
		shape so that the bomber can safely begin to clear bricks 
		from his starting location.
		*/
		int tx, ty;
		for(start_pos = starting_loc.begin();
			start_pos != starting_loc.end();
			start_pos++)
		{
			tx = start_pos->x;
			ty = start_pos->y;

			tiles[tile_index(tx,ty)].type.type_index = tEMPTY;
			if(tx % 2 == 0) //horizontal is in line with a block
			{
				//however this implies fewer L drawing restrictions from border cases
				if(prob(0.5))
					tx--;
				else
					tx++;

					tiles[tile_index(tx,ty)].type.type_index = tEMPTY;
					if(ty > 1)
					{
						if(ty < sH) //this case is unlikely, similar in below  code
						{	if(prob(0.5))
								tiles[tile_index(tx,ty-1)].type.type_index = tEMPTY;
							else
								tiles[tile_index(tx,ty+1)].type.type_index = tEMPTY;}
						else
							tiles[tile_index(tx,ty-1)].type.type_index = tEMPTY;
					}
					else
						tiles[tile_index(tx,ty+1)].type.type_index = tEMPTY;
			}
			else if(ty % 2 == 0)
			{
				if(prob(0.5))
					ty--;
				else
					ty++;

					tiles[tile_index(tx,ty)].type.type_index = tEMPTY;
					if(tx > 1)
					{
						if(tx < sW) //this case is unlikely, similar in below  code
						{	if(prob(0.5))
								tiles[tile_index(tx-1,ty)].type.type_index = tEMPTY;
							else
								tiles[tile_index(tx+1,ty)].type.type_index = tEMPTY;}
						else
							tiles[tile_index(tx-1,ty)].type.type_index = tEMPTY;
					}
					else
						tiles[tile_index(tx+1,ty)].type.type_index = tEMPTY;
			}
			else //neither is aligned with a block
			{
				if(tx > 1)
				{
					if(tx < sW)
					{	if(prob(0.5)) //50% chance
							tiles[tile_index(tx+1,ty)].type.type_index = tEMPTY;
						else
							tiles[tile_index(tx-1,ty)].type.type_index = tEMPTY;}
					else
						tiles[tile_index(tx-1,ty)].type.type_index = tEMPTY;	
				}
				else
					tiles[tile_index(tx+1,ty)].type.type_index = tEMPTY;

				if(ty > 1)
				{
					if(ty < sH)
					{	if(prob(0.5)) //50% chance
							tiles[tile_index(tx,ty+1)].type.type_index = tEMPTY;
						else
							tiles[tile_index(tx,ty-1)].type.type_index = tEMPTY;}
					else
						tiles[tile_index(tx,ty-1)].type.type_index = tEMPTY;
				}
				else
					tiles[tile_index(tx,ty+1)].type.type_index = tEMPTY;
			}
		}



		return starting_loc;

	} //end of map generator



	//empty init() call generates this preset stage for 
	vector<Coordinates> init()
	{
		return gen_random_map(12,16,4,DEFAULT_BRICK_DENSITY);
	}
};
#endif